mod get;
pub use get::Get;

mod set;
pub use set::Set;

mod unknown;
pub use unknown::Unknown;

use crate::{connection::Connection, db::Db, frame::Frame, parse::Parse, Result};

#[derive(Debug)]
pub enum Command {
    Get(Get),
    Set(Set),
    Unknown(Unknown),
}

impl Command {
    pub fn from_frame(frame: Frame) -> Result<Self> {
        let mut parse = Parse::new(frame)?;
        let command_name = parse.next_string()?.to_lowercase();

        let command = match &command_name[..] {
            "get" => Command::Get(Get::parse_frames(&mut parse)?),
            "set" => Command::Set(Set::parse_frames(&mut parse)?),
            _ => return Ok(Command::Unknown(Unknown::new(command_name))),
        };

        parse.finish()?;

        Ok(command)
    }

    pub async fn apply(self, db: &Db, dst: &mut Connection) -> Result<()> {
        match self {
            Command::Get(cmd) => cmd.apply(db, dst).await,
            Command::Set(cmd) => cmd.apply(db, dst).await,
            Command::Unknown(cmd) => cmd.apply(dst).await,
        }
    }
}
